package ng.map;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.nio.MappedByteBuffer;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;

import ng.lib.Vector2D;

public class Map {
	private HashMap<Integer, MapObject> objects = new HashMap<Integer, MapObject>();
	private Image backgroundImage;
	int width, height;
	private double gravitation = 1;
	private Deque<MapObject> MapBuffer = new ArrayDeque<MapObject>();

	public Map(int width, int height) {
		this.width = width;
		this.height = height;
	}

	public void setBackgroundImage(Image i) {
		this.backgroundImage = i;
	}

	/**
	 * adds a {@link MapObject} to the {@link MappedByteBuffer}
	 * @param o The Object to add
	 */
	public void addMapObject(MapObject o) {
		this.MapBuffer.push(o);
	}

	/**
	 * Add every element from MapBufer to Hash Map
	 */
	public void clearMapBuffer() {
		while (!MapBuffer.isEmpty()) {
			this.objects.put(MapBuffer.peek().getId(), MapBuffer.poll());
		}
	}

	synchronized public void draw(Graphics2D g2) {
		for (MapObject o : objects.values()) {
			o.paintComponent(g2);
		}
	}

	synchronized public void draw(Graphics2D g2, Rectangle r) {
		for (MapObject o : objects.values()) {
			if (r.contains(o.getPosition()))
				o.paintComponent(g2);
		}

		g2.setColor(Color.BLACK);
		g2.drawRect(0, 0, this.width - 1, this.height - 1);

	}

	public void tick() {
		clearMapBuffer();
		// Gravitation
		for (MapObject o1 : objects.values())
			for (MapObject o2 : objects.values()) {
				Vector2D d = Vector2D.add(o1.getPosition(),
						o2.getPosition().clone().multiply(-1)).multiply(
						(float) gravitation);
				double distance = d.getValue();
				if (distance > 0) {
					double f = (o1.getMass() * o2.getMass()) / distance;
					if (f != 0) {
						d.contractTo(f);
						if (o2 instanceof MapObjectDynamic)
							((MapObjectDynamic) o2).getSpeed().add(d);
						if (o1 instanceof MapObjectDynamic)
							((MapObjectDynamic) o1).getSpeed().add(
									d.multiply(-1));

					}
				}
			}

		for (MapObject o : objects.values()) {
			if (o instanceof MapObjectDynamic)
				// ((MapObjectDynamic) o).getSpeed().add(new Vector2D(0, 0.2f));

				o.tick();
		}
	}
}
